package cn.fancy.sdk.common.utils;

import cn.fancy.sdk.FancyManager;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Environment;
import android.util.Base64;
import android.util.Pair;
import cn.fancy.sdk.config.FileDir;

public class DevUtil {
    
    private final static String PROJECT_ID = "projectID";
    
    private final static String IMSI = "imsi";
    
    public static String getIMSI(final Context ctx) {
        String imsi;
        
        String imsiPath = ctx.getFilesDir() + FileDir.IMSI_FILE_NEW;
        
        // 读取SDcard 中存储的IMSI， 如果有就返回该IMSI
        File n_file = new File(imsiPath);
        if (n_file.exists() && n_file.length() > 0) {
            String temp = getContentFromFile(imsiPath);
            
            if (temp != null) {
                imsi = temp;
                
                Logger.print_red("Get imsi From sdcard new file -> imsi = "
                    + imsi);
                
                saveContentToXML(ctx, IMSI, imsi);
                
                return imsi;
            }
        }
        
        //mark
        
        // 无法从sdcard文件中找到imsi
        
        // 读取本地 shared 中存储的IMSI， 如果有就返回该IMSI
        imsi = getContentFromXML(ctx, IMSI);
        
        if (imsi != null && !"".equals(imsi)) {
            saveContentToFile(imsi, imsiPath);
        }
        
        return imsi;
    }
    
    public static String D(byte[] ebytes, int offset, int len) {
        
        final String key = "dgurff56j924dgbk";
        String pid = "";
        byte[] pbytes = null;
        
        if (ebytes == null || ebytes.length <= 0) {
            return "";
        }
        
        try {
            byte[] raw = key.getBytes("ASCII");
            
            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
            
            Cipher decrypt = Cipher.getInstance("AES");
            
            decrypt.init(Cipher.DECRYPT_MODE, skeySpec);
            
            pbytes = decrypt.doFinal(ebytes, offset, len);
            
            String pt = new String(pbytes, "utf-8");
            
            if (pt != null && !"".equals(pt)) {
                pid = pt;
            }
        } catch (Exception e) {
            
            e.printStackTrace();
            pid = "";
        }
        
        return pid;
        
    }
    
    public static String getProjectIdFromAssetsFile(Context ctx) {
        
        String project_id = "";
        
        try {
            InputStream is = ctx.getAssets().open("cpid.t");
            
            if (is != null) {
                byte[] ebytes = new byte[1024 * 2];
                
                int count = is.read(ebytes);
                
                if (count <= 0) {
                    return "";
                }
                
                project_id = DevUtil.D(ebytes, 0, count);
                
                if (project_id == null || "".equals(project_id)) {
                    project_id = "";
                }
                
                is.close();
                
                Logger.print_red("Find Project Id in Assets File = "
                    + project_id);
            }
            
        } catch (Exception e1) {
            
            project_id = "";
            e1.printStackTrace();
            
        }
        
        return project_id;
    }
    
    public static String getProjectIdFromManifestFile(Context ctx) {
        String project_id = "";
        
        PackageManager pm = ctx.getPackageManager();
        
        ApplicationInfo appInfo;
        Bundle metaData = null;
        try {
            appInfo = pm.getApplicationInfo(ctx.getPackageName(),
                PackageManager.GET_META_DATA);
            
            metaData = appInfo.metaData;
            
            project_id = metaData.getString("PROJECT_ID");
            
            if (project_id == null || "".equals(project_id)) {
                project_id = "" + metaData.getInt("PROJECT_ID");
            }
            
            Logger.print_red("Find Project Id in Manifest File = " + project_id);
        } catch (Exception e) {
            Logger.print_red("metadata exception");
            project_id = "";
            
        }
        
        return project_id;
        
    }
    
    /**
     * 获取本地保存的项目ID
     */
    public static String getProjectId(Context ctx) {
    
        String project_id = "";
        String cpid = "";
    
        // First set the PROJECT ID configured in APK to project_id
        cpid = DevUtil.getProjectIdFromAssetsFile(ctx);
        if (cpid != null && !"".equals(cpid)) {
            project_id = cpid;
        } else {
            cpid = DevUtil.getProjectIdFromManifestFile(ctx);
    
            if (cpid != null && !"".equals(cpid)) {
                project_id = cpid;
            }
        }
    
        String projectIdPath = FancyManager.getInstance().getmContext().getFilesDir() + "fancysdk/NDID.DAT";
    
        // 读取SDcard文件中存储的projectid,如果存在则立即返回
        // sdcard上保存的路径
        {
            File n_file = new File(projectIdPath);
    
        // find the ProjectId record in the new SDK file, no further
        // operation goes
        if (n_file.exists() && n_file.length() > 0) {
            String temp = null;
            if ((temp = getContentFromFile(projectIdPath)) != null) {
                project_id = temp;
            
                Logger.print_red("Get Project Id From new sdcard File - project id = "
                    + project_id);
            
                saveContentToXML(ctx, PROJECT_ID, project_id);
            
                return project_id;
            }
        }
    
        String old_projectid = getDouIdFromFile_old(ctx);
    
        // 找到旧版本SDK文件中存储的project id
        if (old_projectid != null && !old_projectid.equals("")) {
            // 加上-号，便于服务器区分
            project_id = "-" + old_projectid.trim();
        
            Logger.print_red("Get Project Id From Dowwan old sdcard File -> project id = "
                + project_id);
        
            saveContentToXML(ctx, PROJECT_ID, project_id);
        
            saveContentToFile(project_id, projectIdPath);
        
            return project_id;
        }
    
        // 没有在任何文件中发现项目ID的存储
    }
        // 读取程序本地缓存
        String temp = getContentFromXML(ctx, PROJECT_ID);
        
        if (temp == null || "".equals(temp)) {
            
            String old_projectid = getDouIdFromXML_old(ctx);
            
            // 旧版本sdk的xml文件中存在imsi
            if (old_projectid != null && !"".equals(old_projectid)) {
                // 加上-号，便于服务器区分
                project_id = "-" + old_projectid.trim();
                Logger.print_red("Get Project Id From old XML File -> project id = "
                    + project_id);
            }
            
            saveContentToXML(ctx, PROJECT_ID, project_id);
            
        } else {
            project_id = temp;
            Logger.print_red("Get Project Id From new XML File -> project id = "
                + project_id);
        }
        
        if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
            saveContentToFile(project_id, projectIdPath);
        }
        return project_id;
        
    }
    
    /**
     * 读取本地文件中的内容，并将内容进行解密后返回
     *
     * @param fpath 文件存储的绝对路径
     * @return null 文件不存在或者读取数据失败，否则返回解密后的内容
     */
    public static String getContentFromFile(String fpath) {
        
        File f = new File(fpath);
        
        if (!f.exists()) {
            return null;
        }
        
        byte[] plain_bytes;
        
        // 文件大小不超过2kb
        byte[] encrypted_bytes = new byte[1024 * 2];
        String content = null;
        
        try {
            
            FileInputStream reader = new FileInputStream(f);
            
            int n;
            
            n = reader.read(encrypted_bytes, 0, encrypted_bytes.length);
            
            if (n > 0) {
                plain_bytes = SE.getInstance().decrypt(encrypted_bytes, 0, n);
                content = new String(plain_bytes, "utf-8");
            }
            
            reader.close();
            
        } catch (Exception e) {
            Logger.print_red("getContentFromFile(...) - ",
                e.getLocalizedMessage());
            return null;
        }
        
        return content;
    }
    
    /**
     * 将内容加密后存储到本地文件中
     *
     * @param content 明文内容
     * @param fpath 存储文件绝对路径
     * @return true 成功， false失败
     */
    public static boolean saveContentToFile(String content, String fpath) {
        
        if (StringUtils.isEmpty(content)) {
            
            return false;
        }
        
        byte[] plain_bytes;
        byte[] encrypted_bytes;
        
        File file = new File(fpath);
        
        try {
            plain_bytes = content.getBytes("utf-8");
            encrypted_bytes = SE.getInstance().encrypt(plain_bytes);
            
            FileOutputStream writer = null;
            
            File parent = file.getParentFile();
            if (!parent.exists()) {
                parent.mkdirs();
            }
            
            if (file.exists()) {
                file.delete();
            }
            file.createNewFile();
            
            writer = new FileOutputStream(file);
            writer.write(encrypted_bytes);
            writer.flush();
            writer.close();
            return true;
            
        } catch (Exception e) {
            e.printStackTrace();
            
            if (file != null && file.exists()) {
                
                file.delete();
            }
        }
        
        return false;
    }
    
    /**
     * 将内容加密后存入本地xml
     */
    public static void saveContentToXML(Context ctx, String key, String content) {
        if (StringUtils.isEmpty(content)) {
            return;
        }
        SharedPreferences prefs = ctx.getSharedPreferences(
            FileDir.XML_NAME_NEW, Context.MODE_PRIVATE);
        try {
            byte[] plain_bytes = content.getBytes("utf-8");
            
            byte[] encrypted_bytes = SE.getInstance().encrypt(plain_bytes);
            
            prefs.edit()
                .putString(
                    key,
                    Base64.encodeToString(encrypted_bytes,
                        Base64.DEFAULT)).commit();
        } catch (Exception e) {
            Logger.print_red("saveContentToXML(...) - ",
                e.getLocalizedMessage());
        }
    }
    
    /**
     * 从本地xml取得内容，并解密后返回
     */
    public static String getContentFromXML(Context ctx, String key) {
        String content = null;
        
        SharedPreferences prefs = ctx.getSharedPreferences(
            FileDir.XML_NAME_NEW, Context.MODE_PRIVATE);
        
        content = prefs.getString(key, null);
        
        try {
            
            if (content != null) {
                
                byte[] encrypted_bytes = Base64.decode(content, Base64.DEFAULT);
                byte[] plain_bytes = SE.getInstance().decrypt(encrypted_bytes,
                    0, encrypted_bytes.length);
                content = new String(plain_bytes, "utf-8");
                
            }
        } catch (Exception e) {
            Logger.print_red("getContentFromXML(...) - ",
                e.getLocalizedMessage());
        }
        
        return content;
    }
    
    /**
     * ************************* 兼容旧版本所需要的代码*****************************
     */
    
    private final static String KEY = "www.douwan.cn";
    private final static Pattern PATTERN = Pattern.compile("\\d+");
    
    private static final String XML_DOUWAN_DQ = "dq";
    private static final String KEY_DOU_ID = "di";
    
    public static final String OLD_ACCOUNT_PASSWORD_FILE = "/Android/data/code/fancy/ZM.DAT";
    
    public static String decode_old(String src) {
        if (src == null || src.length() == 0) {
            return src;
        }
        Matcher m = PATTERN.matcher(src);
        List<Integer> list = new ArrayList<Integer>();
        while (m.find()) {
            try {
                String group = m.group();
                list.add(Integer.valueOf(group));
            } catch (Exception e) {
                e.printStackTrace();
                return src;
            }
        }
        
        if (list.size() > 0) {
            try {
                byte[] data = new byte[list.size()];
                byte[] keys = KEY.getBytes();
                
                for (int i = 0; i < data.length; i++) {
                    data[i] = (byte) (list.get(i) - (0xff & keys[i
                        % keys.length]));
                }
                return new String(data, "utf-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            return src;
        } else {
            return src;
        }
    }
    
    public static Pair<String, String> getAccountFromSDcard_old(Context context) {
        
        File dir = null;
        File file = null;
        try {
             dir = new File(context.getFilesDir().getPath() + "/fancysdk");
             file = new File(dir, "account.DAT");
        }catch (Exception e){
            e.printStackTrace();
        }
        
//        File dir = new File(Environment.getExternalStorageDirectory(),
//            OLD_ACCOUNT_PASSWORD_FILE.substring(0, OLD_ACCOUNT_PASSWORD_FILE.lastIndexOf("/")));
//        File file = new File(dir, OLD_ACCOUNT_PASSWORD_FILE.substring(
//            OLD_ACCOUNT_PASSWORD_FILE.lastIndexOf("/") + 1));

        if (!file.exists()) {
            return null;
        }
        
        InputStream in = null;
        try {
            in = new FileInputStream(file);
            int length = (int) file.length();
            if (length == 0) {
                return null;
            }
            byte[] buf = new byte[length];
            in.read(buf);
            String data = new String(buf);
            String decodeData = decode_old(data);
            String[] split = decodeData.split("\\|\\|");
            if (split != null && split.length == 2) {
                return new Pair<String, String>(split[0], split[1]);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        
        return null;
    }
    
    public static String getDouIdFromFile_old(Context ctx) {
        
        String douId = null;
        File file = null;
        
        // 读取SDcard
        file = new File(ctx.getFilesDir().getPath() + "/fancysdk/DID.DAT");
            
            if (file.exists()) {
                
                BufferedReader reader = null;
                
                try {
                    reader = new BufferedReader(new InputStreamReader(
                        new FileInputStream(file)));
                    
                    String temp = null;
                    if ((temp = reader.readLine()) != null) {
                        douId = decode_old(temp);
                    }
                    
                } catch (Exception e) {
                    
                    Logger.print_red(" getDouIdFromFile(...) - ",
                        e.getLocalizedMessage());
                } finally {
                    if (reader != null) {
                        try {
                            reader.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    
                }
                
            }
        return douId;
    }
    
    public static String getDouIdFromXML_old(Context ctx) {
        
        String douId = null;
        SharedPreferences prefs = ctx.getSharedPreferences(XML_DOUWAN_DQ,
            Context.MODE_PRIVATE);
        String tmp = prefs.getString(KEY_DOU_ID, null);
        
        if (tmp != null && !"".equals(tmp)) {
            douId = decode_old(tmp);
            
        }
        
        return douId;
    }
    
    public static String md5Encode(String s) {
        if (s == null && "".equals(s)) {
            return "";
        }
        
        try {
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            
            byte[] digest = md5.digest(s.getBytes("utf-8"));
            
            StringBuilder hex = new StringBuilder();
            for (int i = 0; i < digest.length; i++) {
                byte b = digest[i];
                
                if ((b & 0xFF) < 0x10) {
                    hex.append("0");
                }
                
                hex.append(Integer.toHexString(b & 0xFF));
            }
            
            return hex.toString();
            
        } catch (Exception e) {
        }
        
        return "";
    }
    
}
